package com.codebase.alicloud.sts;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse.Credentials;
/**
 * @describe: OSS临时访问凭证授权
 * @author:houkai
 * @Date: 2018/3/7 14:54
 * @version 1.0
 */
public class STSUtil {

    /**目前只有"cn-hangzhou"这个region可用, 不要使用填写其他region的值*/
    private static final String REGION_CN_HANGZHOU = "cn-hangzhou";
    /**当前 STS API 版本*/
    private static final String STS_API_VERSION = "2015-04-01";
    /**必须是https请求*/
    private static final ProtocolType PROTOCOL_TYPE = ProtocolType.HTTPS;
    /**指定角色的全局资源描述符(Aliyun Resource Name，简称Arn)*/
    private static final String ROLE_ARN = "";
    /**用户自定义参数。此参数用来区分不同的Token，可用于用户级别的访问审计*/
    private static final String ROLE_SESSION_NAME = "";

    public static void main(String[] args){
        String bucketName = "";
        String accessKeyId = "";
        String accessKeySecret = "";
        String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
        Long expirationTime = 900L;
        Credentials credentials = createSTSForPutObject(bucketName, ROLE_ARN,accessKeyId, accessKeySecret, expirationTime);
        System.out.println(credentials);
    }

    /**
     * 创建上传临时账号
     * @param bucketName
     * @param roleArn 需要授权的角色名称
     * @param accessKeyId       账号
     * @param accessKeySecret   密码
     * @param expirationTime    过期时间，单位为秒
     * @return
     */
    public static Credentials createSTSForPutObject(String bucketName, String roleArn, String accessKeyId, String accessKeySecret, Long expirationTime) {
        String policy = STSUtil.getPutObjectPolicy(bucketName);
        return createSTS(policy, roleArn,accessKeyId, accessKeySecret, expirationTime);
    }

    /**
     * 创建只读临时授权
     * @param bucketName
     * @param roleArn 需要授权的角色名称
     * @param accessKeyId       账号
     * @param accessKeySecret   密码
     * @param expirationTime    过期时间，单位为秒
     * @return
     */
    public static Credentials createSTSForReadOnly(String bucketName, String roleArn, String accessKeyId, String accessKeySecret, Long expirationTime) {
        String policy = STSUtil.getOSSReadOnlyAccessPolicy(bucketName);
        return createSTS(policy, roleArn, accessKeyId, accessKeySecret, expirationTime);
    }

    /**
     * 创建STS
     * @param policy   授权策略
     * @param roleArn 需要授权的角色名称
     *  @param accessKeyId       账号
     * @param accessKeySecret   密码
     * @param expirationTime    过期时间，单位为秒
     * @return
     */
    private static Credentials createSTS(String policy, String roleArn, String accessKeyId, String accessKeySecret, Long expirationTime) {
        try {
            IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setDurationSeconds(expirationTime);
            request.setVersion(STS_API_VERSION);
            request.setMethod(MethodType.POST);
            request.setProtocol(PROTOCOL_TYPE);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(ROLE_SESSION_NAME);
            request.setPolicy(policy);
            //实体用户获取角色身份的安全令牌的方法
            AssumeRoleResponse response = client.getAcsResponse(request);
            Credentials credentials = response.getCredentials();
            return credentials;
        } catch (ClientException e) {
            e.printStackTrace();
            throw new RuntimeException("创建STS 失败");
        }
    }

    /**
     * 自定义授权策略，对当前bucket下的文件夹读写
     * @param bucketName
     * @return
     */
    private static String getPutObjectPolicy(String bucketName) {
        return String.format(
                "{\n" +
                        "    \"Version\": \"1\", \n" +
                        "    \"Statement\": [\n" +
                        "        {\n" +
                        "            \"Action\": [\n" +
                        "                \"oss:PutObject\" \n" +
                        "            ], \n" +
                        "            \"Resource\": [\n" +
                        "                \"acs:oss:*:*:%s/*\"\n" +
                        "            ], \n" +
                        "            \"Effect\": \"Allow\"\n" +
                        "        }\n" +
                        "    ]\n" +
                        "}", bucketName);
    }

    /**
     * 只读访问该bucket对象存储服务(OSS)的权限，授权策略
     * @param bucketName
     * @return
     */
    private static String getOSSReadOnlyAccessPolicy(String bucketName) {
        return String.format("{\n" +
                "  \"Statement\": [\n" +
                "    {\n" +
                "      \"Action\": [\n" +
                "        \"oss:Get*\",\n" +
                "        \"oss:List*\"\n" +
                "      ],\n" +
                "      \"Effect\": \"Allow\",\n" +
                "      \"Resource\": [\n" +
                "        \"acs:oss:*:*:%s/*\"\n" +
                "      ]\n" +
                "    }\n" +
                "  ],\n" +
                "  \"Version\": \"1\"\n" +
                "}", bucketName);
    }

}
